use sea_orm::Condition;
use std::fmt;

#[derive(Debug, Clone, PartialEq)]
pub enum QueryToken {
    Word(String),
    And,
    Or,
    LeftParen,
    RightParen,
}

#[derive(Debug, Clone)]
pub enum QueryNode {
    Term(String),
    And(Box<QueryNode>, Box<QueryNode>),
    Or(Box<QueryNode>, Box<QueryNode>),
}

#[derive(Debug)]
pub enum ParseError {
    UnexpectedToken(String),
    UnmatchedParentheses,
    EmptyExpression,
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ParseError::UnexpectedToken(token) => write!(f, "意外的标记: {}", token),
            ParseError::UnmatchedParentheses => write!(f, "括号不匹配"),
            ParseError::EmptyExpression => write!(f, "空表达式"),
        }
    }
}

pub struct QueryParser;

impl QueryParser {
    /// 解析查询字符串为抽象语法树
    pub fn parse(query: &str) -> Result<QueryNode, ParseError> {
        let tokens = Self::tokenize(query)?;
        if tokens.is_empty() {
            return Err(ParseError::EmptyExpression);
        }
        
        let mut parser = Parser::new(tokens);
        parser.parse_expression()
    }

    /// 将查询字符串分词
    fn tokenize(query: &str) -> Result<Vec<QueryToken>, ParseError> {
        let mut tokens = Vec::new();
        let mut current_word = String::new();
        let mut chars = query.chars().peekable();

        while let Some(ch) = chars.next() {
            match ch {
                ' ' | '\t' | '\n' | '\r' => {
                    if !current_word.is_empty() {
                        tokens.push(Self::word_to_token(current_word.clone()));
                        current_word.clear();
                    }
                }
                '(' => {
                    if !current_word.is_empty() {
                        tokens.push(Self::word_to_token(current_word.clone()));
                        current_word.clear();
                    }
                    tokens.push(QueryToken::LeftParen);
                }
                ')' => {
                    if !current_word.is_empty() {
                        tokens.push(Self::word_to_token(current_word.clone()));
                        current_word.clear();
                    }
                    tokens.push(QueryToken::RightParen);
                }
                '"' => {
                    // 处理引号内的短语
                    let mut phrase = String::new();
                    while let Some(inner_ch) = chars.next() {
                        if inner_ch == '"' {
                            break;
                        }
                        phrase.push(inner_ch);
                    }
                    if !phrase.is_empty() {
                        tokens.push(QueryToken::Word(phrase));
                    }
                }
                _ => {
                    current_word.push(ch);
                }
            }
        }

        if !current_word.is_empty() {
            tokens.push(Self::word_to_token(current_word));
        }

        Ok(tokens)
    }

    /// 将单词转换为对应的标记
    fn word_to_token(word: String) -> QueryToken {
        match word.to_uppercase().as_str() {
            "AND" | "&&" | "和" => QueryToken::And,
            "OR" | "||" | "或" => QueryToken::Or,
            _ => QueryToken::Word(word),
        }
    }
}

struct Parser {
    tokens: Vec<QueryToken>,
    position: usize,
}

impl Parser {
    fn new(tokens: Vec<QueryToken>) -> Self {
        Self { tokens, position: 0 }
    }

    fn current_token(&self) -> Option<&QueryToken> {
        self.tokens.get(self.position)
    }

    fn advance(&mut self) -> Option<&QueryToken> {
        if self.position < self.tokens.len() {
            self.position += 1;
        }
        self.current_token()
    }

    fn parse_expression(&mut self) -> Result<QueryNode, ParseError> {
        self.parse_or_expression()
    }

    fn parse_or_expression(&mut self) -> Result<QueryNode, ParseError> {
        let mut left = self.parse_and_expression()?;

        while let Some(QueryToken::Or) = self.current_token() {
            self.advance(); // 消费 OR 标记
            let right = self.parse_and_expression()?;
            left = QueryNode::Or(Box::new(left), Box::new(right));
        }

        Ok(left)
    }

    fn parse_and_expression(&mut self) -> Result<QueryNode, ParseError> {
        let mut left = self.parse_primary_expression()?;

        while let Some(token) = self.current_token() {
            match token {
                QueryToken::And => {
                    self.advance(); // 消费 AND 标记
                    let right = self.parse_primary_expression()?;
                    left = QueryNode::And(Box::new(left), Box::new(right));
                }
                QueryToken::Word(_) => {
                    // 隐式 AND：两个相邻的词默认为 AND 关系
                    let right = self.parse_primary_expression()?;
                    left = QueryNode::And(Box::new(left), Box::new(right));
                }
                _ => break,
            }
        }

        Ok(left)
    }

    fn parse_primary_expression(&mut self) -> Result<QueryNode, ParseError> {
        match self.current_token() {
            Some(QueryToken::Word(word)) => {
                let word = word.clone();
                self.advance();
                Ok(QueryNode::Term(word))
            }
            Some(QueryToken::LeftParen) => {
                self.advance(); // 消费左括号
                let expr = self.parse_expression()?;
                
                match self.current_token() {
                    Some(QueryToken::RightParen) => {
                        self.advance(); // 消费右括号
                        Ok(expr)
                    }
                    _ => Err(ParseError::UnmatchedParentheses),
                }
            }
            Some(token) => Err(ParseError::UnexpectedToken(format!("{:?}", token))),
            None => Err(ParseError::EmptyExpression),
        }
    }
}

impl QueryNode {
    /// 将查询节点转换为 Sea-ORM 的 Condition
    pub fn to_condition<F>(&self, field_matcher: F) -> Condition
    where
        F: Fn(&str) -> Condition + Clone,
    {
        match self {
            QueryNode::Term(term) => field_matcher(term),
            QueryNode::And(left, right) => {
                Condition::all()
                    .add(left.to_condition(field_matcher.clone()))
                    .add(right.to_condition(field_matcher))
            }
            QueryNode::Or(left, right) => {
                Condition::any()
                    .add(left.to_condition(field_matcher.clone()))
                    .add(right.to_condition(field_matcher))
            }
        }
    }

    /// 获取查询中的所有关键词
    pub fn get_keywords(&self) -> Vec<String> {
        match self {
            QueryNode::Term(term) => vec![term.clone()],
            QueryNode::And(left, right) | QueryNode::Or(left, right) => {
                let mut keywords = left.get_keywords();
                keywords.extend(right.get_keywords());
                keywords
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_simple_term() {
        let result = QueryParser::parse("张三").unwrap();
        assert!(matches!(result, QueryNode::Term(_)));
    }

    #[test]
    fn test_and_expression() {
        let result = QueryParser::parse("张三 AND 李四").unwrap();
        assert!(matches!(result, QueryNode::And(_, _)));
    }

    #[test]
    fn test_or_expression() {
        let result = QueryParser::parse("张三 OR 李四").unwrap();
        assert!(matches!(result, QueryNode::Or(_, _)));
    }

    #[test]
    fn test_parentheses() {
        let result = QueryParser::parse("(张三 OR 李四) AND 1990").unwrap();
        assert!(matches!(result, QueryNode::And(_, _)));
    }

    #[test]
    fn test_implicit_and() {
        let result = QueryParser::parse("张三 李四").unwrap();
        assert!(matches!(result, QueryNode::And(_, _)));
    }

    #[test]
    fn test_quoted_phrase() {
        let result = QueryParser::parse("\"张三 李四\"").unwrap();
        if let QueryNode::Term(term) = result {
            assert_eq!(term, "张三 李四");
        } else {
            panic!("Expected Term node");
        }
    }

    #[test]
    fn test_chinese_operators() {
        let result = QueryParser::parse("张三 和 李四").unwrap();
        assert!(matches!(result, QueryNode::And(_, _)));

        let result = QueryParser::parse("张三 或 李四").unwrap();
        assert!(matches!(result, QueryNode::Or(_, _)));
    }
}